package com.resource.controller;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;

import javax.annotation.Resource;

import org.apache.commons.collections4.ListUtils;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.resource.configuration.http.HttpClientUtils;
import com.resource.dto.ContractImportDto;
import com.resource.query.ContractQuery;
import com.resource.query.ContractValidateQuery;
import com.resource.request.ContractArchiveRequest;
import com.resource.request.ContractSaveRequest;
import com.resource.response.OfficeResponse;
import com.resource.service.ContractService;
import com.resource.service.OfficeTokenService;
import com.resource.utils.EasyExcelUtil;
import com.resource.utils.ResultBody;
import com.resource.utils.ServiceResultHandler;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 合同 controller
 *
 * @author jianghao.zhang
 */
@Slf4j
@RestController
@RequestMapping(value = "/api/contract")
public class ContractController {

	@Resource
	private ContractService contractService;

	/**
	 * [分页查询]合同列表
	 *
	 * @param query
	 *            查询参数
	 * @return 分页列表
	 */
	@GetMapping("/list")
	public ResultBody queryPage(ContractQuery query) {
		return ServiceResultHandler
				.process((Function<Object, Object>) o -> contractService.queryPage((ContractQuery) o), query);
	}

	/**
	 * [查询]合同详情
	 *
	 * @param id
	 *            合同id
	 * @return 详情信息
	 */
	@GetMapping("/{id}")
	public ResultBody queryOne(@PathVariable Integer id) {
		return ServiceResultHandler
				.process((Function<Object, Object>) o -> contractService.queryContractById((Integer) o), id);
	}

	/**
	 * [添加]合同
	 *
	 * @param request
	 *            合同信息
	 * @return 操作结果
	 */
	@PostMapping
	public ResultBody add(@RequestBody ContractSaveRequest request) {
		return ServiceResultHandler
				.process((Consumer<Object>) (o) -> contractService.addContract((ContractSaveRequest) o), request);
	}

	/**
	 * [修改]合同
	 *
	 * @param request
	 *            合同信息
	 * @return 操作结果
	 */
	@PutMapping
	public ResultBody update(@RequestBody ContractSaveRequest request) {
		return ServiceResultHandler
				.process((Consumer<Object>) (o) -> contractService.updateContract((ContractSaveRequest) o), request);
	}

	/**
	 * [删除]合同
	 *
	 * @param id
	 *            合同id
	 * @return 操作结果
	 */
	@DeleteMapping("/{id}")
	public ResultBody delete(@PathVariable("id") Integer id) {
		return ServiceResultHandler.process((Consumer<Object>) (o) -> contractService.deleteContract((Integer) o), id);
	}

	/**
	 * [数据校验]合同编号或合同标题是否重复
	 *
	 * @param query
	 *            查询参数
	 * @return "true" 是，"false" 否
	 */
	@PostMapping("/validateNumberTitle")
	public String validateRepeatedTitleOrNumber(ContractValidateQuery query) {
		return contractService.validateRepeatedNumber(query);
	}

	/**
	 * [数据外发]合同归档
	 *
	 * @param req
	 *            泛微外发数据
	 * @return 处理结果
	 */
	@PostMapping("/updateContractArchive")
	public String updateContractArchive(ContractArchiveRequest req) {
		contractService.updateContractArchive(req);
		return "true";
	}

	/**
	 * 合同导入
	 *
	 * @param file
	 * @return
	 */
	@PostMapping("/import/fq")
	public String importProject(MultipartFile file) {
		List<Object> list = new ArrayList<>();
		try {
			list = EasyExcelUtil.readExcel(file, new ContractImportDto(), 1, 1);
		} catch (IOException e) {
			log.error("excel resolve fail:", e);
			return "fail";
		}

		List<List<Object>> partition = ListUtils.partition(list, list.size() / 5);
		log.info("线程处理数量:{}", partition.size());
		for (int i = 0; i < partition.size(); i++) {
			List<Object> objects = partition.get(i);
			new Thread(() -> {
				objects.stream().forEach(e -> {
					try {

						ContractImportDto dto = (ContractImportDto) e;
						String attachments = dto.getAttachments();
						List<String> attachmentList = new ArrayList<>();
						if (StrUtil.isNotBlank(attachments)) {
							String[] split = attachments.split(";");
							for (int j = 0; j < split.length; j++) {
								String url = split[j].trim();
								String attachmentId = upload(url);
								attachmentList.add(attachmentId);
							}
						}
						if (StrUtil.isNotBlank(dto.getUserIds())) {
							List<String> userIds = Arrays.asList(dto.getUserIds().split(","));
							List<String> users=new LinkedList<>();
							users.add("admin");
							users.addAll(userIds);
							dto.setUser_id(users);
						}else{
							dto.setUser_id(Arrays.asList("admin"));
						}
						dto.setField_44(attachmentList);

						if(StrUtil.isNotBlank(dto.getField_12())){
							Long aLong = Long.valueOf(dto.getField_12());
							if(aLong>0){
								dto.setField_12(DateUtil.format(new Date(aLong), "yyyy-MM-dd"));
							}

						}
						if(StrUtil.isNotBlank(dto.getField_13())){
							Long aLong = Long.valueOf(dto.getField_13());
							if(aLong>0){
								dto.setField_13(DateUtil.format(new Date(aLong), "yyyy-MM-dd"));
							}
						}
						contractService.importContract(dto);
					} catch (Exception ex) {
						log.error("出现异常", ex);
						log.error("{}数据处理失败：{},", Thread.currentThread().getName(), JSONUtil.toJsonStr(e));
					}
				});
				log.info("{}处理完成", Thread.currentThread().getName());
			}, i + "任务").start();
		}
		return "处理中。。。。。。";
	}

	@Resource


	private OfficeTokenService officeTokenService;

	@Value("${office.api.url}")
	private String apiUrl;

	public String upload(String urlPath) throws Exception {
		String url = apiUrl + "/eoffice10/server/public/api/attachment/upload";
		// 设置请求头
		HttpHeaders headers = new HttpHeaders();
		MediaType type = MediaType
				.parseMediaType("multipart/form-data; boundary=----WebKitFormBoundaryR9DKZ0NMoqIeF94D");
		headers.setContentType(type);
		String token = officeTokenService.getToken("admin");
		headers.set("Authorization", "Bearer " + token);
		String fileName = urlPath.substring(urlPath.lastIndexOf("/") + 1);
		URL uri = new URL(urlPath);
		String date = DateUtil.format(new Date(), "yyyyMMdd");
		File file = new File("/tmp/" + date + File.separator + fileName);
		FileUtils.copyURLToFile(uri, file);
		MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
		form.add("Filedata", new FileSystemResource(file));
		form.add("chunks", 1);
		form.add("abbreviation", "other");
		form.add("name", fileName);
		form.add("chunk", 0);
		// 用HttpEntity封装整个请求报文
		HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers);
		ResponseEntity<OfficeResponse> responseEntity = HttpClientUtils.getClient().postForEntity(url, files,
				OfficeResponse.class);
		log.info("附件上传返回：{}", JSONUtil.toJsonStr(responseEntity));
		OfficeResponse body = responseEntity.getBody();
		JSONObject jsonObject = JSONUtil.parseObj(body);
		String attachmentId = (String) jsonObject.getByPath("$.data.attachment_id");
		return attachmentId;
	}
}
